;
;**************************************************************
;*
;*           ACIA Routines
;*
;**************************************************************
;
;ACIA registers
SIO_REG     equ 0xDE
SIO_DATA    equ 0xDF

;------------------------------------------------------------------------------
; Initialize ACIA
;------------------------------------------------------------------------------
acia_init:
    ld      a, 0x17             ;MB68B50 reset
    out     (SIO_REG), a
    ld      a,0x16
    out     (SIO_REG), a        ;MB68B50 set bardrate to 115200
    ret

;------------------------------------------------------------------------------
; ACIA character output from register c	
;------------------------------------------------------------------------------
acia_putchar:
    in		a,(SIO_REG)
	and 	0x02		        ;mask out TDRE bit
	jp		z,acia_putchar	    ;loop until port ready
	ld		a,c			        ;get the char
	out		(SIO_DATA),a	    ;out to port
	ret

;------------------------------------------------------------------------------
; ACIA character into register a
;------------------------------------------------------------------------------
acia_getchar:
    in 		a,(SIO_REG)	        ;get status
	and 	0x01		        ;check RxRDY bit
	jp 		z,acia_getchar		;loop until char ready
	in 		a,(SIO_DATA)	    ;get char
	and		7fh			        ;strip parity bit
	ret

;------------------------------------------------------------------------------
; ACIC output message
;------------------------------------------------------------------------------
acia_print:
    ld      a,(hl)
    inc     hl
    or      a
    ret     z                   ;return when 0 is encountered
    ld      c,a
    call    acia_putchar
    jp      acia_print

;------------------------------------------------------------------------------
; ACIA dump memory bytes
; hl: memory address
; de: number of bytes
;------------------------------------------------------------------------------
acia_dump:
    ld      a,(hl)
    inc     hl
    ld      c,a
    call    acia_putchar
    dec     de
    ld      a,d
    or      e
    jp      nz,acia_dump
    ret

;
;**************************************************************
;*
;*           Compact Flash Routines
;*
;**************************************************************
;
; D7  D6  D5  D4  D3  D2  D1  D0 
;BUSY RDY DWF DSC DRQ CORR 0 ERR

; CF registers.
CF_BASE     equ 0x98	    ;BASE ADDRESS OF PRIMARY IDE CONTROLLER
CF_REG0	    equ	CF_BASE + 0	;DATA PORT
CF_REG1	    equ	CF_BASE + 1	;READ: ERROR CODE, WRITE: FEATURE
CF_REG2	    equ	CF_BASE + 2	;NUMBER OF SECTORS TO TRANSFER
CF_REG3	    equ	CF_BASE + 3	;SECTOR ADDRESS LBA 0 [0:7]
CF_REG4	    equ	CF_BASE + 4	;SECTOR ADDRESS LBA 1 [8:15]
CF_REG5	    equ	CF_BASE + 5	;SECTOR ADDRESS LBA 2 [16:23]
CF_REG6	    equ	CF_BASE + 6	;SECTOR ADDRESS LBA 3 [24:27 (LSB)]
CF_REG7	    equ	CF_BASE + 7	;READ: STATUS, WRITE: COMMAND

cf_diskno:	defs	1	    ;disk number 0-15
cf_track:	defs	2	    ;two bytes for expansion
cf_sector:	defs	2	    ;two bytes for expansion
cf_hstbuf:	defs	512     ;512 bytes of buffer

;------------------------------------------------------------------------------
; CF Initialize.
;------------------------------------------------------------------------------
cf_init:
    ld      a,0x04                  ;reset.
    out     (CF_REG7),a
init_wait_BSY_reset:
    in      a,(CF_REG7)              ;read status.
    and     0x80                     ;mask out BSY bit.
    jp      nz,init_wait_BSY_reset   ;wait until BSY is cleared
    ld      a,0xE0                   ;LBA3=0, master, mode=LBA.
    out	    (CF_REG6),a            
    ld      a,0x01                   ;8bit transfers.
    out	    (CF_REG1),a
    ld      a,0xEF                   ;set feature command.
    out	    (CF_REG7),a
    ret

;------------------------------------------------------------------------------
; CF read 1 sector, 128 bytes length.
; DE: memory location to place data
; register (A) contains 00h if read success, otherwise 01h.
;------------------------------------------------------------------------------
cf_read:
    in      a,(CF_REG7)                 ;read status.
    and     0x80                        ;mask out BSY bit.
    jp      nz,cf_read                  ;wait until BSY is cleared
rd_wait_RDY_set:
    in      a,(CF_REG7)                 ;read status
    and     0x40                        ;mask out RDY bit
    jp      z,rd_wait_RDY_set           ;wait until RDY is set
    ld 		a,01h						;number of sectors
    out		(CF_REG2),a
    ld 		a,(cf_sector)				;lba bits 0 - 7, sector
    out		(CF_REG3),a
    ld 		a,(cf_track)
    out		(CF_REG4),a				    ;lba bits 8 - 15, track 
    ld 		a,(cf_diskno)
    out		(CF_REG5),a				    ;lba bits 16 - 23, disk
    ld 		a,20h						;read sector command
    out		(CF_REG7),a
rd_wait_DRQ_set:
    in 		a,(CF_REG7)					;read status
    and		08h							;DRQ bit
    jp 		z,rd_wait_DRQ_set		    ;wait until DRQ is set
    ld 		hl,cf_hstbuf	            ;host buffer
rd_read_loop:
    in 		a,(CF_REG0)					;get data
    ld 		(hl),a
    inc		hl
    in 		a,(CF_REG7)					;check status
    and		08h							;DRQ bit
    jp 		nz,rd_read_loop			    ;read loop
    ld 		hl,cf_hstbuf			    ;host buffer
    ld 		b,128						;size of CP/M sector
rd_memcpy:
    ld 		a,(hl)						;get byte from host buffer
    ld 		(de),a						;put in memory
    inc		hl
    inc		de
    djnz 	rd_memcpy				    ;put 128 bytes into memory
    in 		a,(CF_REG7)					;get status
    and		01h							;error bit
    ret

;------------------------------------------------------------------------------
; CF write 1 sector, 128 bytes length.
; DE: memory location to get data
; register (A) contains 00h if read success, otherwise 01h.
;------------------------------------------------------------------------------
cf_write:
            ld      hl,cf_hstbuf
			ld 		b,128				        ;size of cp/M sector
wr_memcpy:
			ld 		a,(de)				        ;get byte from memory
			ld 		(hl),a				        ;put in host buffer
			inc		hl
			inc		de
			djnz 	wr_memcpy		            ;put 128 bytes in host buffer
			ld		hl,cf_hstbuf			    ;location of data to write to disk
wr_wait_BSY_reset:
            in      a,(CF_REG7)                 ;read status.
            and     0x80                        ;mask out BSY bit.
            jp      nz,wr_wait_BSY_reset        ;wait until BSY is cleared
wr_wait_RDY_set:
            in      a,(CF_REG7)                 ;read status
            and     0x40                        ;mask out RDY bit
            jp      z,wr_wait_RDY_set           ;wait until RDY is set
			ld 		a,01h						;number of sectors
            out		(CF_REG2),a
            ld 		a,(cf_sector)				;lba bits 0 - 7, sector
            out		(CF_REG3),a
            ld 		a,(cf_track)
            out		(CF_REG4),a				    ;lba bits 8 - 15, track 
            ld 		a,(cf_diskno)
            out		(CF_REG5),a				    ;lba bits 16 - 23, disk
			ld 		a,30h						;Write sector command
			out		(CF_REG7),a
wr_wait_DRQ_set:
            in 		a,(CF_REG7)					;read status
            and		08h							;DRQ bit
            jp 		z,wr_wait_DRQ_set		    ;wait until DRQ is set
wr_write_loop:
			ld 		a,(hl)
			out		(CF_REG0),a					;write data
			inc		hl
			in 		a,(CF_REG7)					;read status
			and		08h							;DRQ bit
			jp 		nz,wr_write_loop			;write loop
wr_wait_BSY_reset2:
            in      a,(CF_REG7)                 ;read status.
            and     0x80                        ;mask out BSY bit.
            jp      nz,wr_wait_BSY_reset2       ;wait until BSY is cleared
			in 		a,(CF_REG7)					;clear INTRQ
			and		01h							;check for error
			ret

;
;**************************************************************
;*
;*           PS/2 Keyboard Routines
;*
;**************************************************************
;
; kbd ports
KBD_CTRL            equ 0x5F
KBD_DATA            equ 0x5E

; IBM scan code set 1
KBD_SC_ESC          equ 0x01
KBD_SC_1            equ 0x02
KBD_SC_2            equ 0x03
KBD_SC_3            equ 0x04
KBD_SC_4            equ 0x05
KBD_SC_5            equ 0x06
KBD_SC_6            equ 0x07
KBD_SC_7            equ 0x08
KBD_SC_8            equ 0x09
KBD_SC_9            equ 0x0A
KBD_SC_0            equ 0x0B
KBD_SC_MINUS        equ 0x0C
KBD_SC_EQUALS       equ 0x0D
KBD_SC_BACKSPACE    equ 0x0E
KBD_SC_TAB          equ 0x0F
KBD_SC_Q            equ 0x10
KBD_SC_W            equ 0x11
KBD_SC_E            equ 0x12
KBD_SC_R            equ 0x13
KBD_SC_T            equ 0x14
KBD_SC_Y            equ 0x15
KBD_SC_U            equ 0x16
KBD_SC_I            equ 0x17
KBD_SC_O            equ 0x18
KBD_SC_P            equ 0x19
KBD_SC_LBRACKET     equ 0x1A
KBD_SC_RBRACKET     equ 0x1B
KBD_SC_ENTER        equ 0x1C
KBD_SC_LCTRL        equ 0x1D
KBD_SC_A            equ 0x1E
KBD_SC_S            equ 0x1F
KBD_SC_D            equ 0x20
KBD_SC_F            equ 0x21
KBD_SC_G            equ 0x22
KBD_SC_H            equ 0x23
KBD_SC_J            equ 0x24
KBD_SC_K            equ 0x25
KBD_SC_L            equ 0x26
KBD_SC_SEMICOLON    equ 0x27
KBD_SC_QUOTE        equ 0x28
KBD_SC_BACKQUOTE    equ 0x29
KBD_SC_LSHIFT       equ 0x2A
KBD_SC_BACKSLASH    equ 0x2B
KBD_SC_Z            equ 0x2C
KBD_SC_X            equ 0x2D
KBD_SC_C            equ 0x2E
KBD_SC_V            equ 0x2F
KBD_SC_B            equ 0x30
KBD_SC_N            equ 0x31
KBD_SC_M            equ 0x32
KBD_SC_COMMA        equ 0x33
KBD_SC_PERIOD       equ 0x34
KBD_SC_SLASH        equ 0x35
KBD_SC_RSHIFT       equ 0x36
KBD_SC_KP_ASTERISK  equ 0x37
KBD_SC_LALT         equ 0x38
KBD_SC_SPACE        equ 0x39
KBD_SC_CAPSLOCK     equ 0x3A
KBD_SC_F1           equ 0x3B
KBD_SC_F2           equ 0x3C
KBD_SC_F3           equ 0x3D
KBD_SC_F4           equ 0x3E
KBD_SC_F5           equ 0x3F
KBD_SC_F6           equ 0x40
KBD_SC_F7           equ 0x41
KBD_SC_F8           equ 0x42
KBD_SC_F9           equ 0x43
KBD_SC_F10          equ 0x44
KBD_SC_NUMLOCK      equ 0x45
KBD_SC_SCROLLLOCK   equ 0x46
KBD_SC_KP_7         equ 0x47
KBD_SC_KP_8         equ 0x48
KBD_SC_KP_9         equ 0x49
KBD_SC_KP_MINUS     equ 0x4A
KBD_SC_KP_4         equ 0x4B
KBD_SC_KP_5         equ 0x4C
KBD_SC_KP_6         equ 0x4D
KBD_SC_KP_PLUS      equ 0x4E
KBD_SC_KP_1         equ 0x4F
KBD_SC_KP_2         equ 0x50
KBD_SC_KP_3         equ 0x51
KBD_SC_KP_0         equ 0x52
KBD_SC_KP_PERIOD    equ 0x53
KBD_SC_F11          equ 0x57
KBD_SC_F12          equ 0x58
KBD_SC_MASK         equ 0x80

; kbd status bits
KBD_OBF             equ 0x01  ;1 means output buffer full
KBD_IBF             equ 0x02  ;1 means input buffer full
KBD_SYS             equ 0x04  ;0 after power on
KBD_CMD_DATA        equ 0x08  ;1 means command write, 0 means data write
KBD_KEYLOCK         equ 0x10  ;1 means keyboard is not inhibited
KBD_AUX_OBF         equ 0x20  ;1 means mouse output buffer full
KBD_TIMEOUT         equ 0x40  ;1 means timeout error
KBD_PARITY          equ 0x80  ;1 means parity error

; Scancode translation table, nonprintable character is 0
kbd_ascii_table:    equ $
defb  0 , '1',  '2', '3', '4', '5', '6', '7', '8', '9'  ;0x01 - 0x0A
defb '0', '-',  '=',  0 ,  0 , 'q', 'w', 'e', 'r', 't'  ;0x0B - 0x14
defb 'y', 'u',  'i', 'o', 'p', '[', ']',  0 ,  0 , 'a'  ;0x15 - 0x1E
defb 's', 'd',  'f', 'g', 'h', 'j', 'k', 'l', ';', '\'' ;0x1F - 0x28
defb '`',  0 , '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm'  ;0x29 - 0x32
defb ',', '.',  '/',  0 , '*',  0 , ' ',  0 ,  0 ,  0   ;0x33 - 0x3C
defb  0 ,  0 ,   0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0   ;0x3D - 0x46
defb '7', '8', '9',  '-', '4', '5', '6', '+', '1', '2'  ;0x47 - 0x50
defb '3', '0', '.',   0 ,  0 ,  0 ,  0 ,  0             ;0x51 - 0x58

;------------------------------------------------------------------------------
; KBD send command
; register (C) contains the command to write.
;------------------------------------------------------------------------------
kbd_send_cmd:
    in          a,(KBD_CTRL)        ;read status
    and         0x02                ;mask out IBF
    jr          nz,kbd_send_cmd     ;wait until IBF is cleared
    ld          a, c
    out         (KBD_CTRL),a

;------------------------------------------------------------------------------
; KBD send data
; register (C) contains the data to write.
;------------------------------------------------------------------------------
kbd_send_data:
    in          a,(KBD_CTRL)        ;read status
    and         0x02                ;mask out IBF
    jr          nz,kbd_send_data    ;wait until IBF is cleared
    ld          a, c
    out         (KBD_DATA),a

;------------------------------------------------------------------------------
; KBD status
; register (A) contains the status bits
;------------------------------------------------------------------------------
kbd_status:
    in          a,(KBD_CTRL)        ;read status
    ret

;------------------------------------------------------------------------------
; KBD read data
; register (A) contains scan code when any key pressed.
;------------------------------------------------------------------------------
kbd_read:
    in          a,(KBD_CTRL)        ;read status
    and         0x01                ;mask out OBF
    jr          z, kbd_read
    in          a,(KBD_DATA)        ;read data
    ret

;------------------------------------------------------------------------------
; KBD Initialize.
;------------------------------------------------------------------------------
kbd_init:
    ld          c, 0xAA;
    call        kbd_send_cmd
    call        kbd_read
    cp          0x55
    jr          nz, kbd_error
    ld          c, 0x60             ;disable mouse, no interrupt, enable translation
    call        kbd_send_cmd
    call        kbd_send_data
    ld          c, 0xAE
    call        kbd_send_cmd
    ret
kbd_error:
    ld          a, 0x00
    ret         

;------------------------------------------------------------------------------
; KBD scan code to ascii
; register (C) contains scan code
; return key code from register (A)
;------------------------------------------------------------------------------
kbd_ascii:
    ld          a, c
    and         0x7F                ;mask out KBD_SC_MASK (key release)
    cp          KBD_SC_F12
    jr          c, kbd_char
    ld          a,0
    ret
kbd_char:
    ld          hl, kbd_ascii_table
    add         hl, a
    ld          a, (hl)
    ret



    